package org.dfl.plugin.editor;

import org.dfl.plugin.editor.actions.AlignHorizontallyAction;
import org.dfl.plugin.editor.actions.AlignVerticallyAction;
import org.dfl.plugin.editor.actions.CheckHierarchicalAction;
import org.dfl.plugin.editor.actions.ClearFlowStateAction;
import org.dfl.plugin.editor.actions.ConnectionEditAction;
import org.dfl.plugin.editor.actions.LoadAllTokensAction;
import org.dfl.plugin.editor.actions.PauseAction;
import org.dfl.plugin.editor.actions.ResumeAction;
import org.dfl.plugin.editor.actions.ResumeOnceStepAction;
import org.dfl.plugin.editor.actions.ResumeOnceStepDisabledTokensAction;
import org.dfl.plugin.editor.actions.RunAction;
import org.dfl.plugin.editor.actions.SaveAllTokensAction;
import org.dfl.plugin.editor.actions.StopAction;
import org.dfl.plugin.editor.actions.TavernaTransitionEditAction;
import org.dfl.plugin.editor.actions.TransitionEditAction;
import org.dfl.plugin.editor.model.DflDiagram;
import org.eclipse.gef.ContextMenuProvider;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.ui.actions.ActionFactory;

/**
 * Provides context menu actions for the DflEditor
 * 
 * @author Piotr Wlodarczyk
 * 
 */
public class DflEditorContextMenuProvider extends ContextMenuProvider {
	/**
	 * Context menu group for run related actions. Value:
	 * <code>"org.eclipse.gef.group.run"</code>
	 */
	public static final String GROUP_RUN = "org.eclipse.gef.group.run"; //$NON-NLS-1$

	/** The editor's action registry. */
	private ActionRegistry actionRegistry;

	private DflDiagram diagram;

	IMenuListener iMenuListener = new IMenuListener() {
		public void menuAboutToShow(IMenuManager menu) {
			rebuild(menu);
		}
	};

	/**
	 * Instantiate a new menu context provider for the specified EditPartViewer
	 * and ActionRegistry.
	 * 
	 * @param viewer
	 *            the editor's graphical viewer
	 * @param registry
	 *            the editor's action registry
	 * @throws IllegalArgumentException
	 *             if registry is <tt>null</tt>.
	 */
	public DflEditorContextMenuProvider(EditPartViewer viewer,
			ActionRegistry registry, DflDiagram diagram) {
		super(viewer);
		if (registry == null) {
			throw new IllegalArgumentException();
		}
		this.diagram = diagram;
		actionRegistry = registry;
		setRemoveAllWhenShown(true);
		rebuild(this);
		addMenuListener(iMenuListener);
	}

	/**
	 * Called when the context menu is about to show. Actions, whose state is
	 * enabled, will appear in the context menu.
	 * 
	 * @see org.eclipse.gef.ContextMenuProvider#buildContextMenu(org.eclipse.jface.action.IMenuManager)
	 */
	public void buildContextMenu(IMenuManager menu) {
		removeMenuListener(iMenuListener);
		addMenuListener(iMenuListener);
	}

	private void rebuild(IMenuManager menu) {
		IAction action = null;
		// Add standard action groups to the menu
		menu.removeAll();
		menu.setRemoveAllWhenShown(true);
		menu.add(new Separator(GROUP_RUN));
		menu.add(new Separator(GEFActionConstants.GROUP_UNDO));
		menu.add(new Separator(GEFActionConstants.GROUP_EDIT));
		menu.add(new Separator(GEFActionConstants.GROUP_FILE));
		menu.add(new Separator(GEFActionConstants.GROUP_REST));

		if (diagram == null || diagram.isEditable()) {
			// Add actions to the menu
			menu.appendToGroup(GEFActionConstants.GROUP_UNDO, // target group
																// id
					getAction(ActionFactory.UNDO.getId())); // action to add
			menu.appendToGroup(GEFActionConstants.GROUP_UNDO,
					getAction(ActionFactory.REDO.getId()));
			menu.appendToGroup(GEFActionConstants.GROUP_EDIT,
					getAction(ActionFactory.DELETE.getId()));

			action = getAction(TavernaTransitionEditAction.EDIT_TAVERNA);
			if (action.isEnabled())
				menu.appendToGroup(GEFActionConstants.GROUP_EDIT, action);

			action = getAction(TransitionEditAction.EDIT);
			if (action.isEnabled())
				menu.appendToGroup(GEFActionConstants.GROUP_EDIT, action);

			action = getAction(ConnectionEditAction.EDIT);
			if (action.isEnabled())
				menu.appendToGroup(GEFActionConstants.GROUP_EDIT, action);
		}

		// RUN actions
		action = getAction(AlignVerticallyAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GROUP_RUN, action);
		
		action = getAction(AlignHorizontallyAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GROUP_RUN, action);
		
		action = getAction(RunAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GROUP_RUN, action);

		action = getAction(CheckHierarchicalAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GROUP_RUN, action);
		
		action = getAction(PauseAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GROUP_RUN, action);

		action = getAction(ResumeAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GROUP_RUN, action);
		
		action = getAction(ResumeOnceStepAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GROUP_RUN, action);

		action = getAction(ResumeOnceStepDisabledTokensAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GROUP_RUN, action);

		action = getAction(StopAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GROUP_RUN, action);
		
		
		// FILES actions
		action = getAction(SaveAllTokensAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GEFActionConstants.GROUP_FILE, action);

		action = getAction(LoadAllTokensAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GEFActionConstants.GROUP_FILE, action);
		
		action = getAction(ClearFlowStateAction.ACTION_ID);
		if(action.isEnabled()) menu.appendToGroup(GEFActionConstants.GROUP_FILE, action);
		
		action = getAction(ActionFactory.SAVE.getId());
		if(action.isEnabled()) menu.appendToGroup(GEFActionConstants.GROUP_FILE, action);
		
		action = getAction(ActionFactory.PRINT.getId());
		if(action.isEnabled()) menu.appendToGroup(GEFActionConstants.GROUP_REST, action);
	}

	private IAction getAction(String actionId) {
		return actionRegistry.getAction(actionId);
	}
}
